#pragma once

#include "Extension.h"

#include "Class.h"
#include "ExtensionEnd.h"
#include "Property.h"

namespace uml {

const bool Extension::isRequired_default_ = false;
Extension::Extension(const QString& umlType)
    : Classifier(umlType) {}

void Extension::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    Classifier::fromJson(json, errorList);
    Association::fromJson(json, errorList);
    isRequired_ = json.value("isRequired").toBool(isRequired_default_);
    metaclass_ = JsonSerializable::create<Class>(json.value("metaclass"), errorList);

    ownedEnd_ = JsonSerializable::create<ExtensionEnd>(json.value("ownedEnd"), errorList);

}

void Extension::toJson(QJsonObject& json) {
    Classifier::toJson(json);
    Association::toJson(json);
    if (isRequired_ != isRequired_default_) {
        json.insert("isRequired", isRequired_);
    }
    if (metaclass_) {
        QJsonObject metaclass_json;
        metaclass_->toJson(metaclass_json);
        json.insert("metaclass", metaclass_json);
    }
    if (ownedEnd_) {
        QJsonObject ownedEnd_json;
        ownedEnd_->toJson(ownedEnd_json);
        json.insert("ownedEnd", ownedEnd_json);
    }
}

/// <summary>
/// metaclassEnd
    /// The query metaclassEnd() returns the Property that is typed by a metaclass (as
    /// opposed to a stereotype).
/// </summary>
    /// <code>
    /// result = (memberEnd->reject(p | ownedEnd->includes(p.oclAsType(ExtensionEnd)))->any(true))
    /// </code>
shared_ptr<Property> Extension::metaclassEnd() const
{
    return nullptr;
}

/// <summary>
/// isRequired getter
/// Indicates whether an instance of the extending stereotype must be created when
/// an instance of the extended class is created. The attribute value is derived
/// from the value of the lower property of the ExtensionEnd referenced by
/// Extension::ownedEnd; a lower value of 1 means that isRequired is true, but
/// otherwise it is false. Since the default value of ExtensionEnd::lower is 0, the
/// default value of isRequired is false.
/// </summary>
bool Extension::isRequired() const {
    return isRequired_;
}

/// <summary>
/// isRequired setter
/// Indicates whether an instance of the extending stereotype must be created when
/// an instance of the extended class is created. The attribute value is derived
/// from the value of the lower property of the ExtensionEnd referenced by
/// Extension::ownedEnd; a lower value of 1 means that isRequired is true, but
/// otherwise it is false. Since the default value of ExtensionEnd::lower is 0, the
/// default value of isRequired is false.
/// </summary>
void Extension::setIsRequired(bool value) {
    isRequired_ = value;
}

/// <summary>
/// metaclass getter
/// References the Class that is extended through an Extension. The property is
/// derived from the type of the memberEnd that is not the ownedEnd.
/// </summary>
shared_ptr<Class> Extension::metaclass() const {
    return metaclass_;
}

/// <summary>
/// metaclass setter
/// References the Class that is extended through an Extension. The property is
/// derived from the type of the memberEnd that is not the ownedEnd.
/// </summary>
void Extension::setMetaclass(shared_ptr<Class> value) {
    metaclass_ = value;
}

/// <summary>
/// ownedEnd getter
/// References the end of the extension that is typed by a Stereotype.
/// </summary>
shared_ptr<ExtensionEnd> Extension::ownedEnd() const {
    return ownedEnd_;
}

/// <summary>
/// ownedEnd setter
/// References the end of the extension that is typed by a Stereotype.
/// </summary>
void Extension::setOwnedEnd(shared_ptr<ExtensionEnd> value) {
    ownedEnd_ = value;
}

} // namespace uml
